package com.sixbro.authorization.service;

import com.sixbro.common.domain.Scope;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.common.exceptions.InvalidClientException;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.ClientRegistrationException;
import org.springframework.security.oauth2.provider.client.BaseClientDetails;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *
 * </p>
 *
 * @author: Mr.Lu
 * @since: 2021/12/6 14:26
 */
@Component
public class OAuth2ClientDetailsService implements ClientDetailsService {

    private static Collection< ClientDetails > clients;

    static {
        initClients( );
    }

    private static void initClients( ) {
        if ( clients != null ) return;
        clients = new HashSet<>( );
        PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder( );
        //"authorization_code", "password", "refresh_token", "client_credentials", "implcit"

        BaseClientDetails clientConsumer = new BaseClientDetails( );
        clientConsumer.setClientId( "boss" );
        clientConsumer.setClientSecret( passwordEncoder.encode( "dream" ) );
        clientConsumer.setAuthorities( Collections.emptyList( ) );
        clientConsumer.setAdditionalInformation( Collections.emptyMap( ) );
        clientConsumer.setAccessTokenValiditySeconds( 1800 );
        clientConsumer.setRefreshTokenValiditySeconds( 604800 );
        clientConsumer.setAuthorizedGrantTypes( List.of( "password", "refresh_token" ) );
        clientConsumer.setScope( Arrays.stream(Scope.values() ).map( Scope::name ).collect( Collectors.toList( ) ) );
        clientConsumer.setRegisteredRedirectUri( Collections.singleton( "https://api.bossdream.com/oauth/code" ) );
        clients.add( clientConsumer );

        clientConsumer = new BaseClientDetails( );
        clientConsumer.setClientId( "Ym9zc2RyZWFtLXU4LWRlbGVnYXRvci1zZXJ2aWNlLmNsaWVudF9pZAo=" );
        clientConsumer.setClientSecret( passwordEncoder.encode( "Ym9zc2RyZWFtLXU4LWRlbGVnYXRvci1zZXJ2aWNlLmNsaWVudF9zZWNyZXQK" ) );
        clientConsumer.setAuthorities( Collections.emptyList( ) );
        clientConsumer.setAdditionalInformation( Collections.emptyMap( ) );
        clientConsumer.setAccessTokenValiditySeconds( 1800 );
        clientConsumer.setRefreshTokenValiditySeconds( 604800 );
        clientConsumer.setAuthorizedGrantTypes( List.of( "client_credentials" ) );
        clientConsumer.setScope( List.of( "u8" ) );
        clientConsumer.setRegisteredRedirectUri( Collections.singleton( "https://api.bossdream.com/oauth/code" ) );
        clients.add( clientConsumer );
    }

    @Override
    public ClientDetails loadClientByClientId( String clientId ) throws ClientRegistrationException {

        return clients.stream( )
                .filter( clientDetails -> Objects.equals( clientId, clientDetails.getClientId() ) )
                .findFirst()
                .orElseThrow( ( ) -> new InvalidClientException( "Bad client credentials: " + clientId ) );
    }
}
